import React from 'react';
import ReactDOM from 'react-dom';

import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';
import {all, take, select, call, put} from 'redux-saga/effects';

import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

/*ReactDOM.render(<App />, document.getElementById('root'));*/

/*import ReactReduxDemo from "./components/ReactReduxDemo";

function request(url, options) { //fetch的简单封装
    return fetch(url, options)
        .then((response) => {
            if (response.status >= 200 && response.status < 300) {
                return response;
            }

            const error = new Error(response.statusText);
            error.response = response;
            throw error;
        })
        .then((response) => {
            return response.json();
        })
        .then((data) => {
            return data;
        })
        .catch((err) => {
            return err;
        });
}

function reducer(state = 100, action) { //state可以是基础数据类型（整型，字符串等），也可以是数组、对象...
    switch (action.type) {
        case '+1': //可用行为
            console.log(action);
            return action.payload; //实现方法（state不可被改变）
        case '-1':
            console.log(action);
            return action.payload;
        default:
            return state; //一块钱两个，两块钱不卖。要满足行为约定，否则就不会去修改。
    }
}

const sagaMiddleware = createSagaMiddleware(); //创建saga中间件

const store = createStore(reducer, applyMiddleware(sagaMiddleware));//应用saga中间件。通过reducer、sagaMiddleware创建store。简单理解两者，store是存储着数据的仓库，reducer定义了改变仓库（store）中数据的可用行为与具体实现（“同步请求”），saga中间件可将异步请求（如ajax异步）转化成“同步请求”。

function* plus() { //提示：由于generator函数能够在执行过程中暂停（yield），所以可以放心使用while(true){}来实现循环监听
    // all, 以并行方式运行阻塞型调用
    // put, 产生一个action
    // call, 以阻塞方式调用函数
    // fork, 以非阻塞方式调用函数
    // take, action监听拦截一次, 循环监听while(true){}
    // delay, 延迟
    // race, 只处理最先完成的任务

    while (true) { //循环监听
        yield take("+1_REQUEST"); //暂停，直到监听到指定action
        console.log("监听到请求(action)：+1_REQUEST");

        const state = yield select((state) => {
            return state;
        });
        console.log("原值：" + state);

        const data = yield call(request, `http://localhost/react/plus?num=${state}`); //暂停，以阻塞方式调用函数，直到取到数据。提示：使用ES2015/ES6“字符串模板”降低字符串拼接复杂度（反单引号`，1 旁边那个）
        console.log("新值：" + data);

        yield put({type: "+1", payload: data}) //暂停，直到发送action完成
    }
}

function* minus() {
    while (true) {
        yield take("-1_REQUEST"); //暂停，直到监听到指定action
        console.log("监听到请求(action)：-1_REQUEST");

        const state = yield select((state) => {
            return state;
        });
        console.log("原值：" + state);

        const data = yield call(request, "http://localhost/react/minus", {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({num: state})
        }); //暂停，以阻塞方式调用函数，直到取到数据
        console.log("新值：" + data);

        yield put({type: "-1", payload: data}) //暂停，直到发送action完成。payload为自定义名称
    }
}

function* rootSaga() {
    yield all(
        [
            plus(),
            minus()
        ]
    ); //同时执行多个任务
}

sagaMiddleware.run(rootSaga);

//由Provider来监听（subscribe）store中的state，待state发生变化后，对“入口”组件执行渲染操作（“入口”的组件ReactReduxDemo，是被Provider组件包起来的）
//Provider是store的管理者，是状态state的管理者，更是ReactReduxDemo的父组件。Provider是父组件，就意味着，Provider可以将组件内部的“状态state”和“函数”以某种“映射策略”传到子组件ReactReduxDemo的props中（子组件的构造函数）
//扩展：react中常用的存储数据的方式，state和props。父组件向子组件传递数据，通常是以子组件构造函数的方式来传递，通常是传递到子组件的props中。子组件向父组件传递数据，是通过调用父组件传递给子组件的方法来实现的。
ReactDOM.render(<Provider store={store}><ReactReduxDemo/></Provider>, document.getElementById('root'));*/

//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

import ReactReduxDemoExtra from "./components/ReactReduxDemoExtra";

function request(url, options) { //fetch的简单封装
    return fetch(url, options)
        .then((response) => {
            if (response.status >= 200 && response.status < 300) {
                return response;
            }

            const error = new Error(response.statusText);
            error.response = response;
            throw error;
        })
        .then((response) => {
            return response.json();
        })
        .then((data) => {
            return data;
        })
        .catch((err) => {
            return err;
        });
}

function reducer(state = {num: 100}, action) { //state可以是基础数据类型（整型，字符串等），也可以是数组、对象...
    switch (action.type) {
        case '+1': //可用行为
            console.log(action);
            return {...state, num: action.payload}; //实现方法（state不可被改变）
        case '-1':
            console.log(action);
            return {...state, num: action.payload};//ES6解构赋值
        default:
            return state; //一块钱两个，两块钱不卖。要满足行为约定，否则就不会去修改。
    }
}

const sagaMiddleware = createSagaMiddleware(); //创建saga中间件

const store = createStore(reducer, applyMiddleware(sagaMiddleware));//应用saga中间件。通过reducer、sagaMiddleware创建store。简单理解两者，store是存储着数据的仓库，reducer定义了改变仓库（store）中数据的可用行为与具体实现（“同步请求”），saga中间件可将异步请求（如ajax异步）转化成“同步请求”。

function* plus() { //提示：由于generator函数能够在执行过程中暂停（yield），所以可以放心使用while(true){}来实现循环监听
    // all, 以并行方式运行阻塞型调用
    // put, 产生一个action
    // call, 以阻塞方式调用函数
    // fork, 以非阻塞方式调用函数
    // take, action监听拦截一次, 循环监听while(true){}
    // delay, 延迟
    // race, 只处理最先完成的任务

    while (true) { //循环监听
        yield take("+1_REQUEST"); //暂停，直到监听到指定action
        console.log("监听到请求(action)：+1_REQUEST");

        const state = yield select((state) => {
            return state;
        });
        console.log("原值：" + state.num);

        const data = yield call(request, `http://localhost/react/plus?num=${state.num}`); //暂停，以阻塞方式调用函数，直到取到数据。提示：使用ES2015/ES6“字符串模板”降低字符串拼接复杂度（反单引号`，1 旁边那个）
        console.log("新值：" + data);

        yield put({type: "+1", payload: data}) //暂停，直到发送action完成。payload为自定义名称
    }
}

function* minus() {
    while (true) {
        yield take("-1_REQUEST"); //暂停，直到监听到指定action
        console.log("监听到请求(action)：-1_REQUEST");

        const state = yield select((state) => {
            return state.num;
        });
        console.log("原值：" + state);

        const data = yield call(request, "http://localhost/react/minus", {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({num: state})
        }); //暂停，以阻塞方式调用函数，直到取到数据
        console.log("新值：" + data);

        yield put({type: "-1", payload: data}) //暂停，直到发送action完成
    }
}

function* rootSaga() {
    yield all(
        [
            plus(),
            minus()
        ]
    ); //同时执行多个任务
}

sagaMiddleware.run(rootSaga);

ReactDOM.render(<Provider store={store}><ReactReduxDemoExtra/></Provider>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
